﻿using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace FrameWork.Lib.Serialization
{
    public static class SerializerNonWCF
    {



        /// <summary>
        /// Returns the target namespace for the serializer.
        /// </summary>
        public static string TargetNamespace
        {
            get
            {
                return "http://www.w3.org/2001/XMLSchema";
            }
        }
        /// <summary>
        /// Returns the set of included namespaces for the serializer.
        /// </summary>
        /// <returns>
        /// The set of included namespaces for the serializer.
        /// </returns>
        public static XmlSerializerNamespaces GetNamespaces(bool pSuportNamespaces)
        {
            var ns = new XmlSerializerNamespaces();
            if (!pSuportNamespaces)
            {
                ns.Add("", "");
            }
            return ns;
        }


        private static bool DoesSuportNamespaces(System.Type pObjType)
        {
            System.Xml.Serialization.XmlTypeAttribute tAttr = (System.Xml.Serialization.XmlTypeAttribute)Attribute.GetCustomAttribute(pObjType, typeof(System.Xml.Serialization.XmlTypeAttribute));
            return tAttr != null;
        }
        /// <summary>
        /// Serializes the <i>Obj</i> to an XML string.
        /// </summary>
        /// <param name="Obj">
        /// The object to serialize.</param>
        /// <param name="ObjType">The object type.</param>
        /// <returns>
        /// The serialized object XML string.
        /// </returns>
        /// <remarks>
        /// The <see cref="PrettyPrint" /> property provides
        /// an easy-to-read formatted XML string.
        /// </remarks>
        public static string ToXml(object pObj)
        {
            var tObjType = pObj.GetType();
            bool tSupNamespases = DoesSuportNamespaces(tObjType);
            var ser = new XmlSerializer(tObjType);
            var xml = "";
            using (var memStream = new MemoryStream())
            {
                using (var xmlWriter = new XmlTextWriter(memStream, Encoding.Unicode))
                {


                    xmlWriter.Formatting = Formatting.Indented;
                    xmlWriter.Indentation = 1;
                    xmlWriter.IndentChar = Convert.ToChar(9);

                    xmlWriter.Namespaces = true;
                    ser.Serialize(xmlWriter, pObj, Serializer.GetNamespaces(tSupNamespases));
                    xml = Encoding.Unicode.GetString(memStream.GetBuffer());
                    xmlWriter.Close();
                    memStream.Close();
                }
            }

            xml = xml.Substring(xml.IndexOf(Convert.ToChar(60)));
            xml = xml.Substring(0, (xml.LastIndexOf(Convert.ToChar(62)) + 1));

            return xml;
        }
        /// <summary>
        /// Creates an object from an XML string.
        /// </summary>
        /// <param name="Xml">
        /// XML string to serialize.</param>
        /// <param name="ObjType">The object type to create.</param>
        /// <returns>
        /// An object of type <i>ObjType</i>.
        /// </returns>
        public static object FromXml(string Xml, System.Type ObjType)
        {
            object result = null;

            var ser = new XmlSerializer(ObjType);

            using (var stringReader = new StringReader(Xml))
            {
                using (var xmlReader = new XmlTextReader(stringReader))
                {
                    if (ser.CanDeserialize(xmlReader))
                    {
                        result = ser.Deserialize(xmlReader);
                        xmlReader.Close();
                        stringReader.Close();

                    }
                    else
                    {
                        throw new Exception("XML cannot be deserialized: " + Xml);
                    }
                }
            }

            return result;
        }

    }


}

